
    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>MySQL中MVCC的理解 - 学习卡片</title>
      <style>
        body { font-family: sans-serif; background-color: #f0f8ff; color: #333; display: flex; flex-direction: column; align-items: center; padding: 50px 20px; }
        .header h1 { font-size: 32px; }
        .grid-container { display: grid; grid-template-columns: repeat(3, 1fr); gap: 28px; width: 100%; max-width: 1200px; }
        .card-container { perspective: 1200px; cursor: pointer; height: 250px; }
        .card { width: 100%; height: 100%; position: relative; transform-style: preserve-3d; transition: transform 0.7s; border-radius: 16px; box-shadow: 0 4px 16px rgba(0,0,0,0.08); }
        .card-container.flipped .card { transform: rotateY(180deg); }
        .card-face { position: absolute; width: 100%; height: 100%; backface-visibility: hidden; display: flex; flex-direction: column; box-sizing: border-box; border-radius: 16px; background-color: #fff; padding: 24px; }
        .card-back { background-color: #f0fff4; transform: rotateY(180deg); justify-content: space-between; }
        .card-category { font-size: 14px; color: #0052d9; margin-bottom: 8px; font-weight: 500; }
        .card-question { font-size: 20px; font-weight: 500; flex-grow: 1; display: flex; align-items: center; justify-content: center; text-align: center; }
        .card-answer-wrapper { flex-grow: 1; overflow-y: auto; }
        .card-answer { font-size: 15px; line-height: 1.7; }
        .card-footer { font-size: 13px; color: #8a919f; border-top: 1px solid #f0f0f0; padding-top: 16px; margin-top: 16px; }
        .card-source { font-size: 13px; color: #8a919f; border-top: 1px solid #f0f0f0; padding-top: 12px; margin-top: 12px; }
      </style>
    </head>
    <body>
      <div class="header">
        <h1>MySQL中MVCC的理解 - 学习卡片</h1>
      </div>
      <div class="grid-container">
        
    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">理论</div>
          <div class="card-question">MVCC (多版本并发控制) 的核心思想是什么？它如何解决传统锁机制的性能瓶颈？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">理论</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">MVCC的核心思想是通过保存数据的多个历史版本，使得读操作可以读取数据的旧版本，而写操作则生成新版本。这样，读操作无需等待写操作完成，写操作也不会阻塞读操作，读写互不干扰，从而大幅提高系统的并发性能，避免了传统锁机制在高并发场景下因频繁锁争用导致的性能瓶颈。</div>
          </div>
          <div class="card-source">来源: MVCC的核心思想</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">机制</div>
          <div class="card-question">在MySQL InnoDB中，为支持MVCC，每条记录会增加哪些关键的隐式字段？它们各自的作用是什么？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">机制</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">InnoDB会为每条记录增加三个隐藏字段：1) DB_TRX_ID: 记录最后一次修改该行数据的事务ID，用于版本可见性判断。 2) DB_ROLL_PTR: 指向该记录上一个版本的指针，存储在撤销日志(Undo Log)中，用于构建版本链。 3) DB_ROW_ID: 自动递增的行ID，用于行级别的并发控制。</div>
          </div>
          <div class="card-source">来源: 隐藏字段的深入理解</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">技术</div>
          <div class="card-question">什么是“事务视图”（Transaction View / Read View）？它在MVCC中扮演什么角色？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">技术</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">事务视图是MVCC的核心机制之一，它是在事务启动时创建的一个数据快照，记录了当前系统中的活跃事务列表和最大事务ID。它的主要作用是决定当前事务能够看到哪些数据版本，确保事务只能看到其启动前已提交的事务生成的数据版本，从而为每个事务提供一个一致性的数据视图，实现事务间的隔离。</div>
          </div>
          <div class="card-source">来源: 事务视图（Transaction View）与Read View</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">特性</div>
          <div class="card-question">MVCC在“读已提交”(Read Committed)和“可重复读”(Repeatable Read)这两种隔离级别下的行为有何不同？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">特性</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">主要区别在于事务视图（Read View）的创建时机：在“读已提交”级别下，每次读取操作都会创建一个新的Read View，因此一个事务内可以看到其他已提交事务的修改。而在“可重复读”级别下，只在事务开始时创建一次Read View，并在整个事务期间保持不变，确保了在同一事务中多次读取数据的结果一致。</div>
          </div>
          <div class="card-source">来源: MVCC与不同事务隔离级别的结合</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">机制</div>
          <div class="card-question">撤销日志 (Undo Log) 在InnoDB的MVCC实现中承担了哪两个关键作用？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">机制</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">撤销日志记录了每次数据修改前的快照，其关键作用有两个：1. 支持快照读 (Snapshot Read)，事务可以通过撤销日志读取数据的旧版本，以保证一致性读。2. 支持事务回滚 (Transaction Rollback)，当事务需要回滚时，撤销日志提供了恢复数据到原始状态的必要信息。</div>
          </div>
          <div class="card-source">来源: 撤销日志（Undo Log）的作用</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">模式</div>
          <div class="card-question">请区分MVCC中的“快照读”(Snapshot Read)和“当前读”(Current Read)。</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">模式</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">“快照读”是指读取事务视图中可见的数据版本，它不需要加锁，从而避免了锁争用，提高了并发性能。而“当前读”是指读取最新的数据版本，它需要加锁来保证数据的一致性，通常用于更新操作，例如 SELECT ... FOR UPDATE、UPDATE和DELETE语句。</div>
          </div>
          <div class="card-source">来源: 快照读（Snapshot Read）与当前读（Current Read）</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">理论</div>
          <div class="card-question">MVCC机制存在哪些主要的劣势或成本？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">理论</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">MVCC的主要劣势包括：1. 存储开销：需要维护数据的多个版本并管理撤销日志，增加了数据库的存储需求。2. 实现复杂性：依赖复杂的版本链、事务视图等数据结构和算法，增加了系统的开发和维护成本。3. 延迟和资源消耗：遍历版本链可能增加读操作的延迟，同时版本管理会消耗额外的CPU和内存资源。</div>
          </div>
          <div class="card-source">来源: MVCC的劣势</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">特性</div>
          <div class="card-question">MVCC是如何保障数据一致性的？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">特性</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">MVCC通过“快照隔离”机制来保障数据一致性。当事务开始时，它会创建一个一致性视图（Read View）。在整个事务期间，所有的数据读取都基于这个视图，这确保了同一事务中的多次读取结果是一致的，从而避免了脏读和不可重复读等问题。</div>
          </div>
          <div class="card-source">来源: MVCC的优势 / 2. 数据一致性保障</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">技术</div>
          <div class="card-question">在MySQL支持的事务隔离级别中，哪一个级别不适用MVCC机制，为什么？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">技术</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">MVCC不适用于“读未提交”（Read Uncommitted）隔离级别。因为在此级别下，事务会直接读取最新的数据版本，而不考虑修改该数据的事务是否已经提交，这违背了MVCC基于事务提交状态和版本可见性的基本规则。</div>
          </div>
          <div class="card-source">来源: MVCC在不同隔离级别中的实现</div>
        </div>
      </div>
    </div>

      </div>
    </body>
    </html>
